package datatypes;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static testUtilities.TestUtilities.getPrivateField;

import java.util.List;

import junit.framework.JUnit4TestAdapter;

import org.junit.Before;
import org.junit.Test;

public class IndexedFaceSet_test {
	IndexedFaceSet set;
	Vertex[] v;
	
	
	public static junit.framework.Test suite() {
		return new JUnit4TestAdapter(IndexedFaceSet_test.class);
	}

	@Before
	public void setUp() throws Exception {
		v = new Vertex[4];
		v[1] = new Vertex(0.0, 0.0);
		v[2] = new Vertex(0.0, 1.0);
		v[3] = new Vertex(1.0, 1.0);
		v[4] = new Vertex(1.0, 0.0);
		set = new IndexedFaceSet(false, false, v);
	}

	@Test
	public void testAllEdgesGenerated() {
		set.generateEdges();
		@SuppressWarnings("unchecked")
		List<Edge> edges = (List<Edge>) getPrivateField(set, "candidateEdges");
		assertEquals("Number of edges", 6, edges.size());
		
		@SuppressWarnings("unchecked")
		List<Vertex> vertices = (List<Vertex>) getPrivateField(set, "vertices");
		for (Vertex vertex : vertices) {
			assertEquals("Number of adjacentEdges of vertex " + vertex.index, 3, vertex.getAdjacentEdges().size());
		}
		
		for (Edge edge : edges) {
			Vertex vertex1 = edge.getVertex1();
			Vertex vertex2 = edge.getVertex2();
			assertTrue("Vertex " + vertex1.index + "'s adjacentEdges should contain edge.", vertex1.getAdjacentEdges().contains(edge));
			assertTrue("Vertex " + vertex2.index + "'s adjacentEdges should contain edge.", vertex2.getAdjacentEdges().contains(edge));
		}
	}

	@Test
	public void testAllTrianglesGenerated() {
		set.generateEdges();
		set.generateTriangles();
		
		@SuppressWarnings("unchecked")
		List<Triangle> triangles = (List<Triangle>) getPrivateField(set, "triangles");
		assertEquals("Number of triangles", 4, triangles.size());
	}

	@Test
	public void testRemoveEdge() {
		set.generateEdges();
		Edge edge = (Edge) v[1].getAdjacentEdges().toArray()[0];
		set.removeEdge(edge);
		
		@SuppressWarnings("unchecked")
		List<Edge> edges = (List<Edge>) getPrivateField(set, "candidateEdges");
		assertFalse("removed edge is still there!", edges.contains(edge));
		for (Vertex vertex : set) {
			assertFalse("Removed edge should not be in vertex" + vertex.index + "'s adjacentEdges list.", vertex.getAdjacentEdges().contains(edge));
		}
		
		@SuppressWarnings("unchecked")
		List<Triangle> triangles = (List<Triangle>) getPrivateField(set, "triangles");
		for (Triangle triangle : triangles) {
			assertFalse("Triangle containing removed edge still exists!", triangle.containsEdge(edge));
		}
		
		for (Edge e : edges) {
			List<Triangle> adjacentTrisLeft = e.getTrianglesLeft();
			for (Triangle triangle : adjacentTrisLeft) {
				assertFalse("An edge still has removed Triangle in its adjacentTiangles.", triangle.containsEdge(edge));
			}
			List<Triangle> adjacentTrisRight = e.getTrianglesRight();
			for (Triangle triangle : adjacentTrisRight) {
				assertFalse("An edge still has removed Triangle in its adjacentTiangles.", triangle.containsEdge(edge));
			}
		}
	}

//	@Test
//	public void testEdgesContainingVertex() {
//		fail("Not yet implemented");
//	}
//
//	@Test
//	public void testTrianglesContainingEdge() {
//		fail("Not yet implemented");
//	}

	@Test
	public void testAdd() {
		Vertex v = new Vertex(5.0, 5.0);
		set.add(v);
		assertEquals("Next index", 5, getPrivateField(set, "numberOfVertices"));
		
		@SuppressWarnings("unchecked")
		List<Vertex> vertices = (List<Vertex>)getPrivateField(set, "vertices");
		assertEquals("vertices list should contain 5 elements", 5, vertices.size());
		
		assertEquals("Newly added vertex should be the last element of the vertices list.", v, vertices.get(4));
		
		int vertexIndex = (Integer) getPrivateField(v, "index");
		assertEquals("Newly added vertex index", 4, vertexIndex);
	}
	
	@Test
	public void testDiamondPeakVectorForEdge() {
		Edge e = new Edge(new Vertex(0.0, 0.0), new Vertex(8.0, 0.0));
		Vertex peak1 = set.diamondPeakVectorForEdge(e);
		Vertex expected = new Vertex(-0.0, 1.65685424944);
		assertEquals("", expected, peak1);
	}
	
	@Test
	public void testDiamondPeakVectorForEdge2() {
		Edge e = new Edge(new Vertex(0.0, 0.0), new Vertex(8.0, 8.0));
		Vertex peak1 = set.diamondPeakVectorForEdge(e);
		Vertex expected = new Vertex(-1.65685424944, 1.65685424944);
		assertEquals("", expected, peak1);
	}

//	@Test
//	public void testClear() {
//		fail("Not yet implemented");
//	}
//
//	@Test
//	public void testRemoveInt() {
//		fail("Not yet implemented");
//	}
//
//	@Test
//	public void testRemoveObject() {
//		fail("Not yet implemented");
//	}
//
//	@Test
//	public void testSet() {
//		fail("Not yet implemented");
//	}
//
//	@Test
//	public void testGet() {
//		fail("Not yet implemented");
//	}

}
